Amazon ECSのデプロイにecspressoを使うとビルド・デプロイの境界やアプリ・インフラのIaC境界が明確になる ~ fujiwara-ware OSS ~

Amazon ECSのデプロイにecspressoを使うとビルド・デプロイの境界やアプリ・インフラのIaC境界が明確になる ~ fujiwara-ware OSS ~

クラスメソッドによる2024年OSS支援対象の @fujiwara さん作の ECS デプロイツールの「ecspresso」を紹介してみる
Clock Icon2024.08.13

クラスメソッドは2024年に5つのOSSに対して支援を実施しました

https://dev.classmethod.jp/articles/oss-sponser-2024/

当方が推薦した @fujiwara さん作による Amazon ECSのデプロイツールである ecspressoが選定されたので、簡単に紹介します。

継続的デリバリーの責任範囲を明確にするecspresso

ecspresso(「エスプレッソ」と発音します)はAWSのコンテナサービスAmazon ECSのデプロイツールです。

ECSでのデリバリーを思い出してみましょう。

  • ECSのデリバリーは、新しいコンテナイメージのビルドと、新しいコンテナイメージのデプロイの2つのフェーズに分かれている
  • ECSのデプロイは、タスク定義を更新し、サービスの参照するタスク定義を更新すること
  • 頻繁に更新されるアプリケーションに対して、VPCやALBといったインフラストラクチャの更新頻度は低く、この2つの更新のライフサイクルは大きく異なる

以上を踏まえ、 ecspressoはECSのデプロイにフォーカスするように設計されたツール であり、コンテナが実行されるインフラストラクチャのVPC系リソースは参照するだけです。特に、TerraformでAWSインフラをIaC化されている場合、後述のようにシームレスに連携できます。

ecs-ecspresso-responsibility

ecspressoを導入してデプロイするまでの流れ

既存のECSサービスを ecspresso でデプロイするまでの流れを紹介します。

TerraformでAWSリソースがIaC管理されているものとします。

ecspressoをダウンロード

まずはecspressoをダウンロードします

macOSならbrewからインストールできます

$ brew install kayac/tap/ecspresso

様々なアーキテクチャー向けにバイナリが用意されています。

https://github.com/kayac/ecspresso/releases

既存のサービスを取り込む

ecspresso init コマンドを利用すると、既存サービスを取り込めます。

  • クラスター
  • サービス

を指定し、取り込みましょう。

$ ecspresso init --region ap-northeast-1 --cluster your-cluster --service your-service --config ecspresso.yml

$ ls -1
ecs-service-def.json
ecs-task-def.json
ecspresso.yml

$ cat ecspresso.yml
region: ap-northeast-1
cluster: your-cluster
service: your-service
service_definition: ecs-service-def.json
task_definition: ecs-task-def.json
timeout: "10m0s"

ecspresso.ymlecspresso固有の定義ファイルであり、 ecs-service-def.jsonecs-task-def.json にはECSのサービスとタスクが定義されています。

特に、ecs-service-def.json にはセキュリティグループやサブネットなどインフラ系リソースを確認できます。

...
  "networkConfiguration": {
    "awsvpcConfiguration": {
      "assignPublicIp": "ENABLED",
      "securityGroups": [
        "sg-123"
      ],
      "subnets": [
        "subnet-123",
        "subnet-456"
      ]
    }
  },
...

ecspressoからタスク一覧が見えていることを確認しましょう。

$ ecspresso tasks
2024/08/12 03:22:29 [INFO] ecspresso version: v2.4.0
|                ID                |  TASKDEFINITION  | INSTANCE | LASTSTATUS | DESIREDSTATUS |      CREATEDAT       |       GROUP       |  TYPE   |
+----------------------------------+------------------+----------+------------+---------------+----------------------+-------------------+---------+
| a6f7a3a95be64eb2a4e00383dd5b9a11 | demo-lb-httpd:3 |          | PENDING    | RUNNING       | 2024-08-12T03:22:07Z | service:alb-httpd | FARGATE |

Terraformと連携する

ecspressoの嬉しい機能の一つは、Terafformとシームレスに連携できることです。

具体的には、Terraformのリソース状態をStateファイル(tfstate)で管理していると、AWSリソースIDをTerraformの論理名に置き換えられます。

まず、ecspresso.yml の冒頭で tfstate プラグインを有効化します

plugins:
  - name: tfstate
    config:
      url: s3://YOUR-BUCKET/terraform.tfstate

続いて、サービス定義ファイル(ecs-service-def.json)内のTerraform管理されているリソースを Terraformの論理名で置き換えます。

...
  "networkConfiguration": {
    "awsvpcConfiguration": {
      "assignPublicIp": "ENABLED",
      "securityGroups": [
        "{{ tfstate tfstate `data.aws_security_group.app.id` }}"
      ],
      "subnets": [
        "{{ tfstate `aws_subnet.private_a.id` }}",
        "{{ tfstate `aws_subnet.private_c.id` }}"
      ]
    }
  },
...

Terraformのリソース一覧は $ terraform state list で確認できます。

デプロイ

新しいコンテナイメージをビルドした前提で、このイメージをデプロイしてみましょう。

デプロイ前に便利なdry-runを2つ紹介します。

$ ecspresso diff で設定の差分を確認できます。

$ ecspresso diff
2024/08/12 03:27:41 [INFO] ecspresso version: v2.4.0
--- arn:aws:ecs:ap-northeast-1:123456789012:task-definition/test-httpd:4
+++ ecs-task-def.json
@@ -10,7 +10,7 @@
         "-c"
       ],
       "essential": true,
-      "image": "public.ecr.aws/docker/library/httpd:2.4.61",
+      "image": "public.ecr.aws/docker/library/httpd:2.4.62",
       "name": "httpd-app",
       "portMappings": [
         {

$ ecspresso verify でコンテナが依存するリソースのチェック、例えば、イメージの存在や権限の整合性をチェックできます。

タスク定義で宣言したイメージが存在しない場合のエラー出力例です。

$ ecspresso verify
2024/08/12 03:47:44 [INFO] ecspresso version: v2.4.0
2024/08/12 03:47:44 httpd-alb/your-cluster Starting verify
  TaskDefinition
    ExecutionRole[arn:aws:iam::123456789012:role/ecsTaskExecutionRole]
    --> [OK]
    TaskRole[arn:aws:iam::123456789012:role/ecsTaskRole]
    --> [OK]
    ContainerDefinition[httpd-app]
      Image[123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/not-exist/web-service:2]
      --> [NG] 404 Not Found
    --> [NG] verify Image[123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/not-exist/web-service:2] failed: 404 Not Found
  --> [NG] verify ContainerDefinition[httpd-app] failed: verify Image[123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/not-exist/web-service:2] failed: 404 Not Found
2024/08/12 03:47:45 [ERROR] FAILED. verify TaskDefinition failed: verify ContainerDefinition[httpd-app] failed: verify Image[123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/not-exist/web-service:2] failed: 404 Not Found

最後に $ ecspresso deploy を実行し、タスク定義とサービスを更新し、コンテナが更新されればデプロイ完了です。

$ ecspresso  deploy
2024/08/12 03:40:35 [INFO] ecspresso version: v2.4.0
2024/08/12 03:40:35 httpd-alb/your-cluster Starting deploy 
Service: httpd-alb
Cluster: your-cluster
TaskDefinition: test-httpd:5
Deployments:
   PRIMARY test-httpd:5 desired:1 pending:0 running:1 COMPLETED(ECS deployment ecs-svc/5601475856890297997 completed.)
Events:
2024/08/12 03:40:36 httpd-alb/DevCluster Registering a new task definition...
...
2024/08/12 03:43:43 httpd-alb/your-cluster Service is stable now. Completed!

最後に

Amazon ECSのデプロイツールである @fujiwara さん作の ecspresso を紹介しました。シンプルで狙いが明確なツールのため、導入や評価は容易ではないかと思います。

ecspresso の設計思想は作者本人による次のZennの記事が参考になります

https://zenn.dev/fujiwara/articles/ecspresso-20201221

網羅的なリファレンスがZennで公開されています。

ecspresso handbook v2対応版

既存プロダクトに ecspresso を組み込む場合、現実と向き合った泥臭い対応が求められます。他社の導入事例を参考にしましょう。

なお、 @fujiwara さんは、 ECSデプロイツールの ecspresso 以外にも、AWS Lambdaをデプロイする lambroll、Go版AWS CLI(=静的リンクされたシングルバイナリ版)の awslim、Amazon ECRの溜まったゴミをお掃除する ecrm など、今回紹介しきれなかったたくさんの便利な OSS を開発されています。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.